package com.heima.user.service.impl;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.Date;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.dtos.AppHttpCodeEnum;
import com.heima.common.dtos.ResponseResult;
import com.heima.common.exception.LeadNewsException;
import com.heima.model.user.dtos.CheckRegisterDto;
import com.heima.common.minio.MinIOFileStorageService;
import com.heima.model.user.dtos.ApplyToWemediaDto;
import com.heima.model.user.dtos.LoginDto;
import com.heima.model.user.dtos.RegisterDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.user.pojos.ApUserRealname;
import com.heima.user.mapper.ApUserMapper;
import com.heima.user.mapper.ApUserRealnameMapper;
import com.heima.user.service.ApUserService;
import com.heima.utils.common.BCrypt;
import com.heima.utils.common.JwtUtils;
import com.heima.utils.common.RsaUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.poi.hssf.record.DVALRecord;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.PrivateKey;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import static org.bouncycastle.asn1.x500.style.RFC4519Style.c;
import static org.bouncycastle.asn1.x500.style.RFC4519Style.cn;

/**
 * ServiceImpl： 就是IService接口的实现类，具体编写BaseMapper实现逻辑
 */
@Service

@Transactional
@Slf4j
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements ApUserService {
    @Value("${leadnews.jwt.privateKeyPath}")
    private String privateKeyPath;

    @Value("${leadnews.jwt.expire}")
    private Integer expire;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private MinIOFileStorageService storageService;

    @Autowired
    private ApUserRealnameMapper apUserRealnameMapper;

    @Override
    public ResponseResult<Map<String, Object>> login(LoginDto dto) {

        //判断是否用户登录还是访客登录
        if(StringUtils.isNotEmpty(dto.getPhone())
                && StringUtils.isNotEmpty(dto.getPassword())){
            //用户登录

            //校验用户名和密码
            QueryWrapper<ApUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("phone",dto.getPhone());
            ApUser loginUser = getOne(queryWrapper);

            if(loginUser==null){
                //return ResponseResult.errorResult(400,"用户名不存在");
               // throw new LeadNewsException(400,"用户名不存在"); //业务异常
                throw new LeadNewsException(AppHttpCodeEnum.AP_USER_DATA_NOT_EXIST);
            }

            if(!BCrypt.checkpw(dto.getPassword(),loginUser.getPassword())){
                //return ResponseResult.errorResult(400,"密码错误");
                throw new LeadNewsException(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR); //业务异常
            }

            //生成token给前端返回
            loginUser.setPassword(null);//在token不存储密码等敏感信息
            try {
                //读取私钥文件
                PrivateKey privateKey = RsaUtils.getPrivateKey(privateKeyPath);
                String token = JwtUtils.generateTokenExpireInMinutes(loginUser, privateKey, expire);

                Map<String,Object> result = new HashMap<>();
                result.put("token",token);
                result.put("user",loginUser);
                return ResponseResult.okResult(result);
            } catch (Exception e) {
                e.printStackTrace();
                //return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
                throw new RuntimeException(e); //系统异常
            }
        }else{
            //访客登录
            try {
                //读取私钥文件
                PrivateKey privateKey = RsaUtils.getPrivateKey(privateKeyPath);
                ApUser user = new ApUser();
                user.setId(0);//访客的ID为0
                String token = JwtUtils.generateTokenExpireInMinutes(user, privateKey, expire);

                Map<String,Object> result = new HashMap<>();
                result.put("token",token);
                return ResponseResult.okResult(result);
            } catch (Exception e) {
                e.printStackTrace();
                //return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
                throw new RuntimeException(e); //系统异常
            }
        }
    }

    @Autowired
    private ApUserMapper apUserMapper;
    /**
     * 用户注册
     * @param dto
     * @return
     */
    @Override
    public ResponseResult appSendSMS(RegisterDto dto) {
        String password = dto.getPassword();
        String username = dto.getUsername();
        String realword = dto.getRealword();
        String phoneNo = dto.getPhoneNo();
        if (username == null ||  phoneNo == null ){
            return  ResponseResult.okResult(400,"用户名、手机号不能为空");
        }
        //获取验证码：
       String code =  createCode(dto);
        ResponseResult responseResult = new ResponseResult();
        responseResult.setCode(200);
        responseResult.setErrorMessage("验证码返回成功");
        responseResult.setData(code);




        return responseResult;
    }
    /**
     * 验证码注册校验,注册用户
     */
    @Override
    public ResponseResult appClientRegister(CheckRegisterDto dto) {
        String code = dto.getCode();
        String password = dto.getPassword();
        String phoneNo = dto.getPhoneNo();
        String realword = dto.getRealword();
        String username = dto.getUsername();
        if (code == null || password == null || phoneNo == null || realword == null || username == null){
            return ResponseResult.errorResult(400,"数据的数据库为空");
        }
        if (!password.equals(realword)){
            return ResponseResult.errorResult(400,"确认密码不正确");
        }

        //校验验证码：
        String key = username + phoneNo;
        String redisCode = redisTemplate.opsForValue().get(key);
        if (redisCode==null || !redisCode.equals(code)){
            return ResponseResult.errorResult(400,"验证码错误");
        }

        //对密码进行加盐加密、存入数据库
        //1-获取随机盐
        String gensalt = BCrypt.gensalt();
        //2-对密码进行加盐加密
        String hashpw = BCrypt.hashpw(password, gensalt);
        //用户对象
        ApUser apUser = new ApUser();
        apUser.setName(username);
        apUser.setPassword(hashpw);
        apUser.setStatus(true);
        apUser.setCreatedTime(new Date());
        apUser.setPhone(phoneNo);
        apUserMapper.insert(apUser);


        return ResponseResult.okResult(200,"用户注册成功");
    }


    /**
     *生成并且验证码返回
     * @param dto
     * @return
     */
    private String createCode(RegisterDto dto) {
        String phoneNo = dto.getPhoneNo();
        String username = dto.getUsername();
        //UUID生成5位随机数
        //查看手机号是否被注册过
        LambdaQueryWrapper<ApUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ApUser::getPhone,phoneNo);
        ApUser apUser = apUserMapper.selectOne(wrapper);
        if (apUser!=null){
            throw new  LeadNewsException(400,"该手机号已被注册");
        }
        //生成6位验证码：
        // 调用阿里云工具类，发送短信
        String code = RandomUtil.randomNumbers(6);
        //自定义key  用户名 + 手机号
        String  key = username + phoneNo;
        redisTemplate.opsForValue().set(key,code, Duration.ofMinutes(2));

        log.info("短信发送成功，手机号 = " + phoneNo   + "，验证码 = " + code);

        return  code;

    }



    @Override
    public ResponseResult apply_to_become_Wemedia(MultipartFile file,ApplyToWemediaDto dto) {//,
        //参数校验
//        if (file == null || dto == null){
        if (file == null){
            throw new LeadNewsException(AppHttpCodeEnum.PARAM_INVALID);
        }

        //拼接文件名
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        //取出文件原名
        String originalFilename = file.getOriginalFilename();
        //获取文件后缀名
        String extName = originalFilename.substring(originalFilename.lastIndexOf("."));
        //最终的文件名
        String fieName = uuid+extName;

        try {
            //存入minIo
            String url = storageService.uploadImgFile("",fieName,file.getInputStream());

            //存储用户信息到DB
            ApUserRealname apUserRealname = new ApUserRealname();
            apUserRealname.setUserId(dto.getUserId().intValue());
            apUserRealname.setName(dto.getName());
            apUserRealname.setIdno(dto.getIdno());
            apUserRealname.setFontImage(url);
            apUserRealname.setStatus((short)1);
            apUserRealname.setCreatedTime(new Date());
            apUserRealname.setSubmitedTime(new Date());

            apUserRealnameMapper.insert(apUserRealname);
        } catch (IOException e) {
            e.printStackTrace();
            log.info("存储文件或者数据库失败: "+e.getMessage());
        }

        return ResponseResult.okResult(null);
    }
}
